using System.Collections;
using System.Collections.Concurrent;
using Google.Protobuf;
using HuaXianQu.ProtoBuffEx.Runtime.ProtoInterface;

public partial class Map : IProtoInit
{
    private ConcurrentDictionary<int, ConcurrentDictionary<string, ConcurrentDictionary<string, MapItem>>>
        _EffectDictMap = null;

    ConcurrentDictionary<int, ConcurrentDictionary<string, ConcurrentDictionary<string, MapItem>>> EffectDictMap
    {
        get
        {
            if (_EffectDictMap == null)
            {
                _EffectDictMap =
                    new ConcurrentDictionary<int,
                        ConcurrentDictionary<string, ConcurrentDictionary<string, MapItem>>>();
                Init();
            }

            return _EffectDictMap;
        }
        set => _EffectDictMap = value;
    }

    private ConcurrentDictionary<string, ConcurrentDictionary<int, MapItem>> _EffectInfoDictMap = null;

    ConcurrentDictionary<string, ConcurrentDictionary<int, MapItem>> EffectInfoDictMap
    {
        get
        {
            if (_EffectInfoDictMap == null)
            {
                _EffectInfoDictMap = new ConcurrentDictionary<string, ConcurrentDictionary<int, MapItem>>();
                Init();
            }

            return _EffectInfoDictMap;
        }
        set => _EffectInfoDictMap = value;
    }

    public void Init()
    {
        if (_EffectDictMap == null)
        {
            _EffectDictMap =
                new ConcurrentDictionary<int, ConcurrentDictionary<string, ConcurrentDictionary<string, MapItem>>>();
        }

        if (_EffectInfoDictMap == null)
        {
            _EffectInfoDictMap = new ConcurrentDictionary<string, ConcurrentDictionary<int, MapItem>>();
        }

        for (int i = 0; i < DataList.Count; i++)
        {
            var item = DataList[i];
            InitEffectDict(item);
            InitEffectInfoDict(item);
        }
    }

    private void InitEffectDict(MapItem item)
    {
        var MapIDMap = EffectDictMap.GetOrAdd(item.MapID,
            key => new ConcurrentDictionary<string, ConcurrentDictionary<string, MapItem>>());
        var RegionTypeMap = MapIDMap.GetOrAdd(item.RegionType, key => new ConcurrentDictionary<string, MapItem>());
        RegionTypeMap.TryAdd(item.MonsterDistribution, item);
    }

    private void InitEffectInfoDict(MapItem item)
    {
        var RegionTypeMap =
            EffectInfoDictMap.GetOrAdd(item.RegionType, key => new ConcurrentDictionary<int, MapItem>());
        RegionTypeMap.TryAdd(item.MapLevel, item);
    }

    public bool GetEffectDictMap<T>(int MapID, out T value) where T : IDictionary
    {
        value = default(T);
        if (EffectDictMap.TryGetValue(MapID, out var MapIDMap))
        {
            value = (T)(IDictionary)MapIDMap;
            return true;
        }

        return false;
    }

    public bool GetEffectDictMap<T>(int MapID, string RegionType, out T value) where T : IDictionary
    {
        value = default(T);
        if (EffectDictMap.TryGetValue(MapID, out var MapIDMap))
        {
            if (MapIDMap.TryGetValue(RegionType, out var RegionTypeMap))
            {
                value = (T)(IDictionary)RegionTypeMap;
                return true;
            }
        }

        return false;
    }

    public bool GetEffectDictMap<T>(int MapID, string RegionType, string MonsterDistribution, out T value)
        where T : IMessage
    {
        value = default(T);
        if (EffectDictMap.TryGetValue(MapID, out var MapIDMap))
        {
            if (MapIDMap.TryGetValue(RegionType, out var RegionTypeMap))
            {
                if (RegionTypeMap.TryGetValue(MonsterDistribution, out var MonsterDistributionMap))
                {
                    value = (T)(IMessage)MonsterDistributionMap;
                    return true;
                }
            }
        }

        return false;
    }

    public bool GetEffectInfoDictMap<T>(string RegionType, out T value) where T : IDictionary
    {
        value = default(T);
        if (EffectInfoDictMap.TryGetValue(RegionType, out var RegionTypeMap))
        {
            value = (T)(IDictionary)RegionTypeMap;
            return true;
        }

        return false;
    }

    public bool GetEffectInfoDictMap<T>(string RegionType, int MapLevel, out T value) where T : IMessage
    {
        value = default(T);
        if (EffectInfoDictMap.TryGetValue(RegionType, out var RegionTypeMap))
        {
            if (RegionTypeMap.TryGetValue(MapLevel, out var MapLevelMap))
            {
                value = (T)(IMessage)MapLevelMap;
                return true;
            }
        }

        return false;
    }
}